/*
 * Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "wfd_enum_napi.h"

namespace OHOS {
namespace Sharing {

napi_status AddNamedProperty(napi_env env, napi_value object, const std::string name, int32_t enumValue)
{
    SHARING_LOGD("trace.");
    napi_status status;
    napi_value enumNapiValue;

    status = napi_create_int32(env, enumValue, &enumNapiValue);
    if (status == napi_ok) {
        status = napi_set_named_property(env, object, name.c_str(), enumNapiValue);
    }

    return status;
}

static napi_value ExportSceneType(napi_env env)
{
    SHARING_LOGD("trace.");
    napi_value result = nullptr;
    napi_status status;

    status = napi_create_object(env, &result);
    if (status == napi_ok) {
        std::string propName = "ERROR_UNKNOWN";
        for (auto itr = mapSceneType.begin(); itr != mapSceneType.end(); ++itr) {
            propName = itr->first;

            status = AddNamedProperty(env, result, propName, itr->second);
            if (status != napi_ok) {
                SHARING_LOGE("Failed to add SceneType prop!");
                break;
            }

            propName.clear();
        }
    }

    if (status != napi_ok) {
        SHARING_LOGE("Failed!");
        napi_get_undefined(env, &result);
        return result;
    }

    napi_object_freeze(env, result);
    return result;
}

static napi_value ExportCodecType(napi_env env)
{
    SHARING_LOGD("trace.");
    napi_value result = nullptr;
    napi_status status;

    status = napi_create_object(env, &result);
    if (status == napi_ok) {
        std::string propName = "ERROR_UNKNOWN";
        for (auto itr = mapCodecType.begin(); itr != mapCodecType.end(); ++itr) {
            propName = itr->first;

            status = AddNamedProperty(env, result, propName, itr->second);
            if (status != napi_ok) {
                SHARING_LOGE("Failed to add CodecType prop!");
                break;
            }

            propName.clear();
        }
    }

    if (status != napi_ok) {
        SHARING_LOGE("Failed!");
        napi_get_undefined(env, &result);
        return result;
    }

    napi_object_freeze(env, result);
    return result;
}

static napi_value ExportAudioFormat(napi_env env)
{
    SHARING_LOGD("trace.");
    napi_value result = nullptr;
    napi_status status;

    status = napi_create_object(env, &result);
    if (status == napi_ok) {
        std::string propName = "ERROR_UNKNOWN";
        for (auto itr = mapAudioFormatId.begin(); itr != mapAudioFormatId.end(); ++itr) {
            propName = itr->first;

            status = AddNamedProperty(env, result, propName, itr->second);
            if (status != napi_ok) {
                SHARING_LOGE("Failed to add FormatId prop!");
                break;
            }

            propName.clear();
        }
    }

    if (status != napi_ok) {
        SHARING_LOGE("Failed!");
        napi_get_undefined(env, &result);
        return result;
    }

    napi_object_freeze(env, result);
    return result;
}

static napi_value ExportVideoFormat(napi_env env)
{
    SHARING_LOGD("trace.");
    napi_value result = nullptr;
    napi_status status;

    status = napi_create_object(env, &result);
    if (status == napi_ok) {
        std::string propName = "ERROR_UNKNOWN";
        for (auto itr = mapVideoFormatId.begin(); itr != mapVideoFormatId.end(); ++itr) {
            propName = itr->first;

            status = AddNamedProperty(env, result, propName, itr->second);
            if (status != napi_ok) {
                SHARING_LOGE("Failed to add FormatId prop!");
                break;
            }

            propName.clear();
        }
    }

    if (status != napi_ok) {
        SHARING_LOGE("Failed!");
        napi_get_undefined(env, &result);
        return result;
    }

    napi_object_freeze(env, result);
    return result;
}

static napi_value ExportDeviceState(napi_env env)
{
    SHARING_LOGD("trace.");
    napi_value result = nullptr;
    napi_status status;

    status = napi_create_object(env, &result);
    if (status == napi_ok) {
        std::string propName = "ERROR_UNKNOWN";
        for (auto itr = mapDeviceState.begin(); itr != mapDeviceState.end(); ++itr) {
            propName = itr->first;

            status = AddNamedProperty(env, result, propName, itr->second);
            if (status != napi_ok) {
                SHARING_LOGE("Failed to add DeviceState prop!");
                break;
            }

            propName.clear();
        }
    }

    if (status != napi_ok) {
        SHARING_LOGE("Failed!");
        napi_get_undefined(env, &result);
        return result;
    }

    napi_object_freeze(env, result);
    return result;
}

static napi_value ExportErrorCode(napi_env env)
{
    SHARING_LOGD("trace.");
    napi_value result = nullptr;
    napi_status status;

    status = napi_create_object(env, &result);
    if (status == napi_ok) {
        std::string propName = "ERROR_UNKNOWN";
        for (auto itr = mapErrorCode.begin(); itr != mapErrorCode.end(); ++itr) {
            propName = itr->first;

            status = AddNamedProperty(env, result, propName, itr->second);
            if (status != napi_ok) {
                SHARING_LOGE("Failed to add ErrorCode prop!");
                break;
            }

            propName.clear();
        }
    }

    if (status != napi_ok) {
        SHARING_LOGE("Failed!");
        napi_get_undefined(env, &result);
        return result;
    }

    napi_object_freeze(env, result);
    return result;
}

napi_status InitEnums(napi_env env, napi_value exports)
{
    SHARING_LOGD("trace.");
    const napi_property_descriptor properties[] = {
        DECLARE_NAPI_PROPERTY("SceneType", ExportSceneType(env)),
        DECLARE_NAPI_PROPERTY("CodecType", ExportCodecType(env)),
        DECLARE_NAPI_PROPERTY("VideoFormat", ExportVideoFormat(env)),
        DECLARE_NAPI_PROPERTY("AudioFormat", ExportAudioFormat(env)),
        DECLARE_NAPI_PROPERTY("DeviceState", ExportDeviceState(env)),
        DECLARE_NAPI_PROPERTY("ErrorCode", ExportErrorCode(env)),
    };

    size_t count = sizeof(properties) / sizeof(napi_property_descriptor);

    return napi_define_properties(env, exports, count, properties);
}

} // namespace Sharing
} // namespace OHOS